package main

import (
	"fmt"
	"image"
	"image/color"
	"image/png"
	"os"
	"runtime"
	"sync"
)

func main() {
	const (
		xmin, ymin, xmax, ymax = -2, -2, +2, +2
		width, height          = 1024, 1024
	)

	//创建一个空图像？
	img := image.NewRGBA(image.Rect(0, 0, width, height))

	//创建任务通道和结果通道
	tasks := make(chan int, height)
	results := make(chan struct {
		y   int
		row []color.Color
	}, height)

	//确定有多少个worker
	numworkers := runtime.NumCPU()
	fmt.Printf("使用 %d个 goroutine\n", numworkers)

	var wg sync.WaitGroup

	for i := 0; i < numworkers; i++ {
		wg.Add(1)
		go func(workerID int) {
			defer wg.Done()
			for y := range tasks {
				//计算一行的像素
				row := make([]color.Color, width)
				for x := 0; x < width; x++ {
					// 将像素坐标转换为复平面上的点
					zx := float64(x)/width*(xmax-xmin) + xmin
					zy := float64(y)/height*(ymax-ymin) + ymin
					z := complex(zx, zy)

					// 计算该点的颜色
					row[x] = mandelbrot(z)
				}
				results <- struct {
					y   int
					row []color.Color
				}{y, row}
			}
		}(i)
		//将计算的结果放到管道里面
	}

	//发送所有任务到任务通道
	go func() {
		for y := 0; y < height; y++ {
			tasks <- y
		}
		close(tasks)
	}()

	//从结果通道接受所有结果, 我们需要接收height个结果
	for i := 0; i < height; i++ {
		result := <-results
		for x, color := range result.row {
			img.Set(x, result.y, color)
		}
	}

	//等待所有worker完成
	wg.Wait()
	close(results)

	png.Encode(os.Stdout, img)
}
